package org.sqlproc.sample.tutorial.model;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToMany;
import javax.persistence.Version;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.NotEmpty;

/**
 * Generated base class, which implements properties and associations for the domain object.
 * <p>
 * Make sure that subclass defines the following annotations:
 * 
 * <pre>
 * @javax.persistence.Entity
 * @javax.persistence.Table(name = "MEDIA")
 * @javax.persistence.Inheritance(strategy=javax.persistence.InheritanceType.JOINED)
 * </pre>
 * 
 */
@MappedSuperclass
// @EntityListeners({org.hibernate.validator.event.JPAValidateListener.class,
// org.fornax.cartridges.sculptor.framework.domain.AuditListener.class
// })
public abstract class MediaBase {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private Long id;
    @Column(name = "TITLE", nullable = false, length = 100)
    @NotEmpty
    private String title;
    @Column(name = "CREATEDDATE")
    @Type(type = "timestamp")
    private Date createdDate;
    @Column(name = "CREATEDBY", length = 50)
    private String createdBy;
    @Column(name = "LASTUPDATED")
    @Type(type = "timestamp")
    private Date lastUpdated;
    @Column(name = "LASTUPDATEDBY", length = 50)
    private String lastUpdatedBy;
    @Version
    @Column(name = "VERSION")
    private Long version;
    @ManyToMany(mappedBy = "media")
    @NotEmpty
    private Set<PhysicalMedia> physicalMedia = new HashSet<PhysicalMedia>();
    @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "media")
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    @NotEmpty
    private Set<Engagement> engagements = new HashSet<Engagement>();
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(name = "EXISTSINMEDIA_MEDIACHARACTER", joinColumns = { @JoinColumn(name = "EXISTSINMEDIA") }, inverseJoinColumns = { @JoinColumn(name = "MEDIACHARACTER") })
    @ForeignKey(name = "FK_EXISTSINMEDIA_MEDIACHARACTER_EXISTSINMEDIA", inverseName = "FK_EXISTSINMEDIA_MEDIACHARACTER_MEDIACHARACTER")
    @NotEmpty
    private Set<MediaCharacter> mediaCharacters = new HashSet<MediaCharacter>();

    public MediaBase() {
    }

    public MediaBase(String title) {
        super();
        // Validate.notNull(title);
        this.title = title;
    }

    public Long getId() {
        return id;
    }

    /**
     * The id is not intended to be changed or assigned manually, but for test purpose it is allowed to assign the id.
     */
    public void setId(Long id) {
        if ((this.id != null) && !this.id.equals(id)) {
            throw new IllegalArgumentException("Not allowed to change the id property.");
        }
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public Date getLastUpdated() {
        return lastUpdated;
    }

    public void setLastUpdated(Date lastUpdated) {
        this.lastUpdated = lastUpdated;
    }

    public String getLastUpdatedBy() {
        return lastUpdatedBy;
    }

    public void setLastUpdatedBy(String lastUpdatedBy) {
        this.lastUpdatedBy = lastUpdatedBy;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    public Set<PhysicalMedia> getPhysicalMedia() {
        return physicalMedia;
    }

    /**
     * Adds an object to the bidirectional many-to-many association in both ends. It is added the collection
     * {@link #getPhysicalMedia} at this side and to the collection
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.PhysicalMedia#getMedia} at the opposite side.
     */
    public void addPhysicalMedia(PhysicalMedia physicalMediaElement) {
        this.physicalMedia.add(physicalMediaElement);
        physicalMediaElement.getMedia().add((Media) this);
    }

    /**
     * Removes an object from the bidirectional many-to-many association in both ends. It is removed from the collection
     * {@link #getPhysicalMedia} at this side and from the collection
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.PhysicalMedia#getMedia} at the opposite side.
     */
    public void removePhysicalMedia(PhysicalMedia physicalMediaElement) {
        this.physicalMedia.remove(physicalMediaElement);
        physicalMediaElement.getMedia().remove((Media) this);
    }

    /**
     * Removes all object from the bidirectional many-to-many association in both ends. All elements are removed from
     * the collection {@link #getPhysicalMedia} at this side and from the collection
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.PhysicalMedia#getMedia} at the opposite side.
     */
    public void removeAllPhysicalMedia() {
        for (PhysicalMedia d : this.physicalMedia) {
            d.getMedia().remove((Media) this);
        }
        this.physicalMedia.clear();

    }

    public Set<Engagement> getEngagements() {
        return engagements;
    }

    /**
     * Adds an object to the bidirectional many-to-one association in both ends. It is added the collection
     * {@link #getEngagements} at this side and the association
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.Engagement#setMedia} at the opposite side is
     * set.
     */
    public void addEngagement(Engagement engagementElement) {
        this.engagements.add(engagementElement);
        engagementElement.setMedia((Media) this);
    }

    /**
     * Removes an object from the bidirectional many-to-one association in both ends. It is removed from the collection
     * {@link #getEngagements} at this side and the association
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.Engagement#setMedia} at the opposite side is
     * cleared (nulled).
     */
    public void removeEngagement(Engagement engagementElement) {
        this.engagements.remove(engagementElement);
        engagementElement.setMedia(null);
    }

    /**
     * Removes all object from the bidirectional many-to-one association in both ends. All elements are removed from the
     * collection {@link #getEngagements} at this side and the association
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.Engagement#setMedia} at the opposite side is
     * cleared (nulled).
     */
    public void removeAllEngagements() {
        for (Engagement d : this.engagements) {
            d.setMedia(null);
        }
        this.engagements.clear();

    }

    public Set<MediaCharacter> getMediaCharacters() {
        return mediaCharacters;
    }

    /**
     * Adds an object to the bidirectional many-to-many association in both ends. It is added the collection
     * {@link #getMediaCharacters} at this side and to the collection
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.MediaCharacter#getExistsInMedia} at the
     * opposite side.
     */
    public void addMediaCharacter(MediaCharacter mediaCharacterElement) {
        this.mediaCharacters.add(mediaCharacterElement);
        mediaCharacterElement.getExistsInMedia().add((Media) this);
    }

    /**
     * Removes an object from the bidirectional many-to-many association in both ends. It is removed from the collection
     * {@link #getMediaCharacters} at this side and from the collection
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.MediaCharacter#getExistsInMedia} at the
     * opposite side.
     */
    public void removeMediaCharacter(MediaCharacter mediaCharacterElement) {
        this.mediaCharacters.remove(mediaCharacterElement);
        mediaCharacterElement.getExistsInMedia().remove((Media) this);
    }

    /**
     * Removes all object from the bidirectional many-to-many association in both ends. All elements are removed from
     * the collection {@link #getMediaCharacters} at this side and from the collection
     * {@link org.fornax.cartridges.sculptor.examples.library.media.domain.MediaCharacter#getExistsInMedia} at the
     * opposite side.
     */
    public void removeAllMediaCharacters() {
        for (MediaCharacter d : this.mediaCharacters) {
            d.getExistsInMedia().remove((Media) this);
        }
        this.mediaCharacters.clear();

    }
}
